home *** CD-ROM | disk | FTP | other *** search
- /*
- * The original copyright owners of the accompanying source code files have
- * agreed to place such code into the public domain. Accordingly, anyone
- * who receives or obtains a copy of such source code is freely entitled to
- * reproduce, use and otherwise exploit such code (including the right to
- * make derivative works), at his/her own risk and expense, without any
- * obligation or liability to the original copyright owners.
- *
- * We would appreciate (but do not require) that the following message be
- * included in any derivative works:
- *
- * "Portions of this program were developed by Peter Broadwell, Rob Myers
- * and Robin Schaufler while working in Silicon Valley."
- *
- * The accompanying source code files and related documentation materials
- * are distributed on an "AS IS" basis, without any warranties or
- * guarantees of any kind. All implied warranties, including the implied
- * warranties of merchantability and of fitness for any particular purpose,
- * are expressly disclaimed.
- */
- #include <stdio.h>
- #include <ctype.h>
- #include "gl.h"
- #include "math.h"
- #include "geom.h"
- #include "colors.h"
- #include "objIds.h"
- #include "class.h"
- #include "classIds.h"
- #include "selectors.h"
- #include "mbox.h"
- #include "individual.h"
- #include "behavior.h"
- #include "doers.h"
- #include "panel.h"
- #include "voxel.h"
- #include "sounds.h"
-
- extern individual *us;
- extern individual *curIndiv;
- extern individual ghostTemplate;
- extern long masterClock;
-
- extern subscr *findvars();
- extern behavior chameleonTemplate;
- extern behavior expanderTemplate;
- extern behavior advancerTemplate;
- extern behavior surfDieTemplate;
- extern behavior wideyeTemplate;
- extern behavior faderTemplate;
-
- #define PI 3.14159265358979323844
- #define DEG(x) ((float)x*(float)180/PI)
- #define RAD(x) ((float)x*PI/(float)180)
-
-
- /*
- * wiggle the target individual
- */
- behavior *
- wiggle(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- register wigglerVars *vars;
- register model *m;
-
- if (vars = (wigglerVars *)target->curVars) {
- vars->angle = vars->magnitude
- * sin(RAD(vars->wiggleClock))
- * cos(5*RAD(vars->wiggleClock));
- vars->wiggleClock+=6;
-
- /* rotate body and tail by opposite angles */
- /* body is first model segment */
- if (m = target->descr) {
- m->rotation.z = -1 * vars->angle;
-
- /* tail is next model segment */
- if (m = m->next)
- m->rotation.z = 7 * vars->angle;
- }
- }
- else fprintf(stderr, "wiggle: can't find instance variables\n");
-
- return self;
- }
-
- editWiggler(self, argtype, him)
- behavior *self; /* WIGGLER */
- int argtype;
- individual *him; /* edit wiggler vars for him */
- {
- panel *p;
- rectangle r;
- wigglerVars *wentry;
-
- extern panel *makePanel();
-
- wentry = (wigglerVars *)him->curVars;
-
- p = (panel *)him->controls;
- setrect(&r, 10, getHighwater(p), 0,0);
- p = p->kids = makePanel(p->kids, p, &r, NULL);
- initVanillaVal(p, 10, 160, &wentry->magnitude, "Flop");
- addBHMenu(self,p,"WIGGLER BEHAVIOR");
- bumpHighwater(p->area.extent.y + 10);
- }
-
- /*
- * advance the target individual around his circle
- */
- behavior *
- advanceTo(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- register circlerVars *vars;
-
- if (vars = (circlerVars *)target->curVars) {
- target->position.x = vars->tether * sin(RAD(vars->circleClock))
- + vars->stake.x;
- target->position.y = vars->tether * cos(RAD(vars->circleClock))
- + vars->stake.y;
- target->position.z = vars->tether * 0.15
- * sin(RAD(vars->circleClock*PI)) + vars->stake.z;
-
- vars->circleClock += vars->circleIncr;
-
- /* Msg(target, MOVE, NOARG, NULL); /* */
- }
- else
- fprintf(stderr, "advanceTo: can't find instance variables\n");
-
- return self;
- }
-
- /*
- * aquire colors from outer space
- */
- behavior *
- altercolor(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- register model *m;
- static rgbcolor newhue;
- register chameleonVars *vars;
-
- if (vars = (chameleonVars *)target->curVars) {
- if (m = target->descr) {
- if (vars->inited == FALSE) {
- gmcolor(m->color, &newhue.r, &newhue.g, &newhue.b);
- vars->nativeColor.r = newhue.r;
- vars->nativeColor.g = newhue.g;
- vars->nativeColor.b = newhue.b;
- vars->inited = TRUE;
- }
- if (vars->influenced == TRUE) {
- mapcaller(m->color, vars->importColor.r,
- vars->importColor.g,
- vars->importColor.b);
- vars->influenced = FALSE;
- }
- else {
- mapcaller(m->color, vars->nativeColor.r,
- vars->nativeColor.g,
- vars->nativeColor.b);
- unsubscribe(&chameleonTemplate, target);
- }
- }
- }
-
- return self;
- }
-
- editColorizer(self, argtype, him)
- behavior *self; /* COLORIZER */
- int argtype;
- individual *him; /* edit colorizer vars for him */
- {
- panel *p;
- rectangle r;
- colorizerVars *centry;
-
- extern panel *makePanel();
-
- centry = (colorizerVars *)him->curVars;
-
- p = (panel *)him->controls;
- setrect(&r, 10, getHighwater(p), 200,getheight()+10);
- p = p->kids = makePanel(p->kids, p, &r, NULL);
- addBHMenu(self,p,"COLORIZER BEHAVIOR");
- bumpHighwater(p->area.extent.y + 10);
- }
-
- /*
- * export color to neighbors
- */
- behavior *
- exportcolor(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- colorizerVars *myvars;
- chameleonVars *hisvars;
- mailbox *vox;
- inst *him;
- register subscr *sentry;
-
- if (myvars = (colorizerVars *)target->curVars) {
- if ((sentry = findvars(target, VOXEL)) == NULL) {
- fprintf(stderr,"exportcolor: can't find my vox\n");
- return NULL;
- }
- vox = (mailbox *)sentry->member;
- for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
- him = sentry->member;
- if ((hisvars = (chameleonVars *)findvars(him, CHAMELEON)) == NULL) {
- subscribe(&chameleonTemplate, him);
- hisvars = (chameleonVars *)findvars(him, CHAMELEON);
- }
- if (hisvars) {
- hisvars->importColor.r = myvars->exportColor.r;
- hisvars->importColor.g = myvars->exportColor.g;
- hisvars->importColor.b = myvars->exportColor.b;
- hisvars->influenced = TRUE;
- }
- else
- fprintf(stderr,"exportcolor: can't get chameleonVars\n");
- }
- }
-
- return self;
- }
-
- /*
- * general purpose advance according to acceleration and velocity
- */
- behavior *
- advance(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- target->velocity.x += target->acceleration.x;
- target->velocity.y += target->acceleration.y;
- target->velocity.z += target->acceleration.z;
-
- target->position.x += target->velocity.x;
- target->position.y += target->velocity.y;
- target->position.z += target->velocity.z;
-
- return self;
- }
-
- /*
- * die if height is at or above surface
- */
- surfaceDie *
- dieAtSurface(self, argtype, target)
- surfaceDie *self;
- int argtype;
- register individual *target;
- {
- if (target->position.z >= self->surface) {
- unsubscribe(us, target);
- Msg(target, FREE, NOARG, NULL); /* get rid of all nested memory */
-
- return NULL;
- }
-
- return self;
- }
-
- /*
- * expand up to scaleMax
- */
- behavior *
- expandScale(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- register expanderVars *vars;
-
- if (vars = (expanderVars *)target->curVars) {
- if (target->scale < vars->scaleMax)
- target->scale *= vars->scaleIncr;
- if (target->scale > vars->scaleMax) {
- target->scale = vars->scaleMax;
- unsubscribe(self, target);
- }
- }
-
- return self;
- }
-
- /*
- * lay calls getMate in order to get a mate for the girl.
- */
- individual *
- getMate(girl, femVars, vox)
- individual *girl;
- femaleVars *femVars;
- mailbox *vox;
- {
- individual *him;
- maleVars *hisVars = NULL;
- subscr *sentry;
- int population, species;
-
- if (femVars->mate) {
- for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
- if (femVars->mate == sentry->member)
- return NULL; /* still mating */
- } /* done mating, so lay them eggs */
- him = (individual *)femVars->mate;
- femVars->mate = NULL;
- return him;
- } else { /* girl has no mate, so look for one. */
- /* first, exercise population growth control */
- if (!girl->them.me.myClass) return NULL;
- species = girl->them.me.myClass->classId;
- population = 1;
- for (sentry = us->them.subscribers; sentry; sentry=sentry->next) {
- if (sentry->member && sentry->member->myClass
- && sentry->member->myClass->classId == species) {
- if (++population > femVars->max_population)
- return NULL;
- }
- }
- /* now look for a mate */
- for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
- him = (individual *)sentry->member;
- /* if mature girl meets mature male of same species */
- if ((hisVars = (maleVars *)findvars(him, MALE))
- && hisVars->interest > 0
- && ! findvars(him, EXPANDER)
- && him->them.me.myClass->classId == girl->them.me.myClass->classId)
- {
- break;
- }
- }
- if (sentry) {
- femVars->mate = sentry->member;
- hisVars->interest = hisVars->min_int;
- }
- return NULL;
- }
- }
-
- /*
- * if a male is nearby, lay eggs.
- */
- behavior *
- lay(self, argtype, girl)
- behavior *self;
- int argtype;
- register individual *girl;
- {
- mailbox *vox;
- individual *mate, *him, *ovum;
- extern individual eggTemplate, metamorphTemplate, *us;
- register subscr *sentry;
- metamorphVars *initMeta;
- femaleVars *femVars = NULL;
- int i, num_of_eggs = 3, n_girls = 2, n_boys = 1;
-
- if (findvars(girl, EXPANDER)) /* immature */
- return self;
- if ((sentry = findvars(girl, VOXEL)) == NULL) {
- fprintf(stderr,"lay: can't find my voxel\n");
- return self;
- }
- vox = (mailbox *)sentry->member;
- if (! (femVars = (femaleVars *)girl->curVars)) {
- fprintf(stderr,"lay: can't find my curvars\n");
- return self;
- }
- if ((mate = getMate(girl, femVars, vox)) == NULL)
- return self;
-
- /*
- * If mate is dead, we can't clone him to make boy babies.
- */
- n_girls = femVars->n_girls;
- n_boys = femVars->n_boys;
- for (sentry = us->them.subscribers; sentry; sentry = sentry->next)
- if (sentry->member == (inst *)mate)
- break;
- if (!sentry) {
- n_girls += n_boys;
- n_boys = 0;
- }
- num_of_eggs = n_girls + n_boys;
-
- /*
- * Only get here if mate has left voxel.
- * should check "us" to see if he is alive before
- * cloning him for male eggs.
- */
-
- /*
- * 0 <= num_of_eggs <= max_eggs.
- */
- for (i=1; i<=num_of_eggs; i++) {
- him = (individual *)clone(i<=n_girls ? girl : mate);
- Msg(him, INIT, NOARG, NULL);
-
- /*******************
- * find a bad egg who exceeds the maximum number of
- * available model indices;
- * blow him away and stop making more of em
- if (TRUE == badModelIndex(him->descr, him)) {
- printf("lay: breaking out due to bad model index at egg %d\n",i);
- Msg(him, FREE, NOARG, NULL);
- break;
- }
- /*************/
-
- him->flags &= ~PICKED;
- him->scale = (long)(0.43 * i) + 2;
-
- sentry = him->them.subscribers; /* for now, forget subscribers */
- him->them.subscribers = NULL;
- sentry = him->them.subscribedTo;
- him->them.subscribedTo = NULL;
- for (; sentry; sentry = sentry->next) {
- if(isSuper(sentry->member, VOXEL)) continue;
- halfsubscr(sentry->member, him);
- if(isSuper(sentry->member, BEHAVIOR)
- && ((behavior *)sentry->member)->varsize) {
- bcopy(&sentry->member, &him->them.subscribedTo->member,
- ((behavior *)sentry->member)->varsize - sizeof(char *));
- if(isSuper(sentry->member, SWERVER)) {
- swerverVars *swerVars =
- (swerverVars *)him->them.subscribedTo;
- /****
- swerVars->maxvelocity.x +=
- (odd(i) ? 1 : -1) *
- (swerVars->maxvelocity.x / (3 + (i>>1)));
- swerVars->maxvelocity.y +=
- (odd(i) ? 1 : -1) *
- (swerVars->maxvelocity.y / (5 + (i>>1)));
- swerVars->maxvelocity.z +=
- (odd(i) ? 1 : -1) *
- (swerVars->maxvelocity.z / (1 + (i>>1)));
- *****/
- }
- }
- }
- him->position.x += 50 * i * (odd(i) ? 1 : -1);
- him->position.y += 100 * i * (odd(i>>1) ? 1 : -1);
- him->position.z += 50 * i * (odd(i>>1) ? -1 : 1);
- him->heading.x *= (odd(i) ? 1 : -1);
- him->heading.y *= (odd(i>>1) ? 1 : -1);
- him->heading.z *= (odd(i>>1) ? -1 : 1);
-
- ovum = (individual *)clone(&eggTemplate);
- subscribe(&metamorphTemplate, ovum);
- initMeta = (metamorphVars *)ovum->them.subscribedTo;
- initMeta->embryo = him;
- initMeta->alarm = 20 * i;
- ovum->position = him->position;
- newVoxPosition(vox, &ovum->position, ovum);
- subscribe(us, ovum);
- Msg(ovum, INIT, 0, NULL);
- }
- doSound(LAY_EGGS);
- return self;
- }
-
- editFemale(self, argtype, him)
- behavior *self; /* FEMALE */
- int argtype;
- individual *him; /* edit female vars for him */
- {
- panel *p;
- rectangle r;
- femaleVars *fentry;
-
- extern panel *makePanel();
-
- fentry = (femaleVars *)him->curVars;
-
- p = (panel *)him->controls;
- setrect(&r, 10, getHighwater(p), 0,0);
- p = p->kids = makePanel(p->kids, p, &r, NULL);
- initVanillaVal(p, 0, 3, &fentry->n_girls, "Girl Eggs");
- initVanillaVal(p, 0, 3, &fentry->n_boys, "Boy Eggs");
- initVanillaVal(p, 3, 5, &fentry->max_population, "Cozy");
- /* initVanillaVal(p, 3, 6, &fentry->max_population, "Cozy"); /**/
- addBHMenu(self,p,"FEMALE BEHAVIOR");
- bumpHighwater(p->area.extent.y + 10);
- }
-
- /*
- * used by fertilize in conjunction with voxSee,
- * such that for each voxel in target's line of sight,
- * chaseGirl gets called.
- */
- chaseGirl(vox, target, path)
- voxel *vox;
- individual *target;
- char *path; /* pointing to char that got me to vox */
- {
- subscr *sentry = NULL;
- maleVars *hisVars = NULL;
- individual *girl;
- double ov_squ = 1, nv_squ = 1; /* how fast am I currently going? */
- point *t_vel;
- point vel_to_girl;
-
- if (! target->them.me.myClass)
- return HALT;
-
- hisVars = (maleVars *)target->curVars;
-
- /* search all individuals in vox */
- for (sentry = vox->mbox.subscribers;
- sentry;
- sentry = sentry->next)
- {
- girl = (individual *)sentry->member;
- if (!girl->them.me.myClass) continue;
- /*
- * upon finding a mature female of the same species,
- * head towards her.
- */
- if (findvars(girl, FEMALE)
- && ! findvars(girl, EXPANDER)
- && target->them.me.myClass->classId == girl->them.me.myClass->classId)
- {
- /* drawVoxel(vox); /* for debugging */
- #define FUD 16
-
- #define ROBS_SWIM
- #ifdef ROBS_SWIM
- vel_to_girl.x = girl->position.x - target->position.x;
- vel_to_girl.y = girl->position.y - target->position.y;
- vel_to_girl.z = girl->position.z - target->position.z;
- /* normalize and set heading to point at girl */
- vtoh(&target->heading, &vel_to_girl);
- #else /* ROBS_SWIM */
- t_vel = &target->velocity;
- ov_squ = (double) (
- t_vel->x * t_vel->x +
- t_vel->y * t_vel->y +
- t_vel->z * t_vel->z + FUD);
- t_vel->x = girl->position.x - target->position.x;
- t_vel->y = girl->position.y - target->position.y;
- t_vel->z = girl->position.z - target->position.z;
- nv_squ = (double) (
- t_vel->x * t_vel->x +
- t_vel->y * t_vel->y +
- t_vel->z * t_vel->z);
- if (nv_squ > ov_squ) {
- ov_squ = sqrt(fabs(ov_squ));
- nv_squ = sqrt(fabs(nv_squ));
- t_vel->x = (t_vel->x * (int)ov_squ) / (int)nv_squ;
- t_vel->y = (t_vel->y * (int)ov_squ) / (int)nv_squ;
- t_vel->z = (t_vel->z * (int)ov_squ) / (int)nv_squ;
- }
- #endif /* ROBS_SWIM */
- hisVars->flags |= FOUND_THIS_TIC;
- return HALT;
- }
- }
- if (isdigit(path[1])
- && hisVars->interest < ((int)path[1]&0xf))
- return HALT;
-
- return CONTINUE;
- }
-
- /*
- * if a female is in the same voxel, fertilize eggs.
- * if a female is in sight, chase her!
- */
- behavior *
- fertilize(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- subscr *entry;
- maleVars *hisEntry;
- wideyeVars *eyevars;
- voxel *vox;
- static char chasePath[] =
- "f1f2furddlluu3RDfurddlluu4RDfurddlluuurrrddddlllluuuu5RRDDfurddlluuurrrddddlllluuuu";
- /* static char chasePath[] = "FfffurddlluuRDfurddlluu"; */
-
- /*
- * for each voxel in line of sight within a given distance,
- * if a subscriber in the voxel is the same class as target
- * and is female,
- * determine point where paths intersect.
- * if that point is ahead of target
- * determine time when she should be there.
- * adjust magnitude of velocity to try to arrive at
- * the same time.
- * else
- * pick a point on her path and aim for it, based
- * on relative slopes of female's and target's paths.
- */
- hisEntry = (maleVars *)target->curVars;
- if (hisEntry->flags & FOUND_THIS_TIC)
- hisEntry->flags = FOUND_LAST_TIC;
- else
- hisEntry->flags = 0;
- if (++hisEntry->tics > hisEntry->rate) {
- hisEntry->tics = 0;
- if (hisEntry->interest < hisEntry->max_int) {
- hisEntry->interest++;
- }
- }
- if (hisEntry->interest <= 0)
- return self;
- entry = findvars(target, VOXEL);
- if (! entry) {
- fprintf(stderr, "fertilize: can't find voxel for %x, class %d\n",
- target, target->them.me.myClass->classId);
- return self;
- }
- vox = (voxel *)entry->member;
-
- voxTurtle(vox, chasePath, &target->delta, chaseGirl, target);
-
- /* if found mate this tic but not last tic, eyes grow wider */
- eyevars = (wideyeVars *)findvars(target, WIDEYE);
- if (hisEntry->flags == FOUND_THIS_TIC) {
- if (eyevars == NULL) {
- subscribe(&wideyeTemplate, target);
- eyevars = (wideyeVars *)findvars(target, WIDEYE);
- }
- }
- if (hisEntry->flags & FOUND_THIS_TIC && eyevars) {
- eyevars->influenced = TRUE;
- eyevars->scalefactor = hisEntry->eyescale;
- }
-
- return self;
- }
-
- editMale(self, argtype, him)
- behavior *self; /* MALE */
- int argtype;
- individual *him; /* edit male vars for him */
- {
- panel *p;
- rectangle r;
- maleVars *mentry;
-
- extern panel *makePanel();
-
- mentry = (maleVars *)him->curVars;
-
- p = (panel *)him->controls;
- setrect(&r, 10, getHighwater(p), 0,0);
- p = p->kids = makePanel(p->kids, p, &r, NULL);
- initVanillaVal(p, mentry->min_int, mentry->max_int,
- &mentry->interest, "Lust");
- initVanillaVal(p, 100, 5, &mentry->rate, "Recovery");
- initVanillaValf(p, 1.5, 3.0, &mentry->eyescale, "Thrill");
- addBHMenu(self,p,"MALE BEHAVIOR");
- bumpHighwater(p->area.extent.y + 10);
- }
-
- /*
- * after some time, change one individual into another.
- */
- behavior *
- altershape(meta, argtype, oldform)
- behavior *meta;
- int argtype;
- register individual *oldform;
- {
- register individual *hatchling;
- expanderVars *vars;
- register subscr *sentry, *nentry;
- metamorphVars *mentry;
- inst *vox;
-
- if(! (mentry = (metamorphVars *)findvars(oldform, METAMORPH)) )
- return meta;
- if (mentry->clock++ > mentry->alarm) {
- if(! (hatchling = mentry->embryo) )
- return meta;
- do_metamorph: /* label to key on in adb */
- /* find egg's voxel */
- sentry = findvars(oldform, VOXEL);
- if(sentry)
- vox = sentry->member;
-
- /*
- * hatchling->subscribers, subscribedTo is just a list
- * of what had subscribed to mom and what mom had
- * subscribed to, respectively.
- * Now hatchling really subscribes.
- */
- for(sentry = hatchling->them.subscribers,
- hatchling->them.subscribers = 0;
- sentry;
- sentry = nentry)
- {
- nentry = sentry->next;
- subscribe(hatchling, sentry->member);
- gffree(sentry);
- }
- for(sentry = hatchling->them.subscribedTo,
- hatchling->them.subscribedTo = 0;
- sentry;
- sentry = nentry)
- {
- nentry = sentry->next;
- subscribe(sentry->member, hatchling);
- if(isSuper(sentry->member, BEHAVIOR)) {
- bcopy(&sentry->member, &hatchling->them.subscribedTo->member,
- ((behavior *)sentry->member)->varsize - sizeof(char *));
- }
- gffree(sentry);
- }
-
- subscribe(&expanderTemplate, hatchling);
- if (vars = (expanderVars *)hatchling->them.subscribedTo) {
- /* hatchling will expand to size its mother was */
- vars->scaleMax = hatchling->scale;
- vars->scaleIncr = 1.01;
- hatchling->scale *= 0.2;
- }
- if(vox)
- newVoxPosition(vox, &hatchling->position, hatchling);
- else
- printf("altershape: couldn't find voxel for indiv %x\n", oldform);
-
- /* Msg(hatchling, INIT, NOARG, NULL); /* */
-
- hatchling->lastPosition.x = hatchling->position.x;
- hatchling->lastPosition.y = hatchling->position.y;
- hatchling->lastPosition.z = hatchling->position.z;
- Msg(oldform, FREE, NOARG, NULL);
- return NULL;
- }
- return meta;
- }
-
- #ifdef NOTDEF
- /*
- * FREEVARS method. Free embryo before freeing metavars.
- NEVER CALLED AS FAR AS I CAN TELL --- peter july 15, 1985
- */
- behavior *
- freeMetaVars(self, argtype, metavars)
- behavior *self; /* METAMORPH */
- int argtype;
- metamorphVars *metavars;
- {
- Msg(metavars->embryo, FREE, NOARG, NULL);
- gffree(metavars);
- return NULL;
- }
- #endif /* NOTDEF */
-
- /*
- * feed calls getDinner in order to get food to feed the feeder.
- */
- individual *
- getDinner(feeder, fentry, vox)
- individual *feeder;
- feederVars *fentry;
- mailbox *vox;
- {
- register subscr *sentry, *uentry;
- individual *dindin;
- unsigned gender;
- int species, count = 0;
- #define NEUTER 0
-
- for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
- dindin = (individual *)sentry->member;
- /* feeder is not his own dinner */
- if (dindin == feeder)
- continue;
- /* if feeder isn't a cannibal, his own species isn't kosher */
- if (!fentry->cannibal
- && dindin->them.me.myClass->classId
- == feeder->them.me.myClass->classId)
- continue;
-
- /* don't eat the last of a gender/species */
- /* HIGH OVERHEAD FOR SOCIAL RESPONSIBILITY! */
- gender = NEUTER;
- if (findvars(dindin, MALE)) gender = MALE;
- else if (findvars(dindin, FEMALE)) gender = FEMALE;
- species = dindin->them.me.myClass->classId;
- for (uentry = us->them.subscribers; uentry; uentry = uentry->next) {
- if (uentry->member != (inst *)dindin
- && uentry->member->myClass->classId == species)
- {
- switch (gender) {
- case NEUTER:
- if (count++)
- return dindin;
- case MALE:
- if (findvars(uentry->member, MALE))
- return dindin;
- break;
- case FEMALE:
- if (findvars(uentry->member, FEMALE))
- return dindin;
- break;
- }
- } /* if member != dindin && classId == species */
- } /* for uentry in us->them.subscribers */
- }
- return NULL;
- }
-
- /*
- * if feeder is in the vicinity of food, feed it.
- */
- behavior *
- feed(self, argtype, feeder)
- behavior *self;
- int argtype;
- individual *feeder;
- {
- mailbox *vox;
- register subscr *sentry;
- expanderVars *bubVars;
- feederVars *fentry;
- individual *dinner, *burp, *makeBub();
-
- if ( !(fentry = (feederVars *)feeder->curVars) )
- return self;
-
- if (++fentry->tics > fentry->rate) {
- fentry->tics = 0;
- if (fentry->interest < fentry->max_int) {
- fentry->interest++;
- }
- }
- if (fentry->interest <= 0)
- return self;
-
- if ((sentry = findvars(feeder, VOXEL)) == NULL) {
- fprintf(stderr,"feed: can't find my voxel\n");
- return self;
- }
- vox = (mailbox *)sentry->member;
- if (dinner = getDinner(feeder, fentry, vox)) {
- expire(dinner, fentry->bubscale);
- fentry->interest = fentry->min_int;
- doSound(MUNCH);
- }
- return self;
- }
-
- editFeeder(self, argtype, him)
- behavior *self; /* FEEDER */
- int argtype;
- individual *him; /* edit feeder vars for him */
- {
- panel *p;
- rectangle r;
- feederVars *fentry;
-
- extern panel *makePanel();
-
- fentry = (feederVars *)him->curVars;
-
- p = (panel *)him->controls;
- setrect(&r, 10, getHighwater(p), 0,0);
- p = p->kids = makePanel(p->kids, p, &r, NULL);
- initVanillaVal(p, fentry->min_int, fentry->max_int,
- &fentry->interest, "Hunger");
- initVanillaVal(p, 100, 5, &fentry->rate, "Metabolism");
- initVanillaValf(p, 50.0, 150.0, &fentry->bubscale, "Satiety");
- addBHMenu(self,p,"FEEDING BEHAVIOR");
- bumpHighwater(p->area.extent.y + 10);
- }
-
- /*
- * widen target's eyes
- */
- behavior *
- wideneye(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- register model *m;
- register wideyeVars *vars;
-
- if (vars = (wideyeVars *)findvars(target, WIDEYE)) {
- if (m = target->descr) {
- if (vars->inited == FALSE) {
- /* for each child of m, multiply scale by scalefactor */
- for (m = m->kids; m; m = m->next) {
- m->scale.x *= vars->scalefactor;
- m->scale.y *= vars->scalefactor;
- m->scale.z *= vars->scalefactor;
- }
- vars->inited = TRUE;
- }
- if (vars->influenced == TRUE) {
- vars->influenced = FALSE;
- }
- else {
- /* for each child of m, divide scale by scalefactor */
- for (m = m->kids; m; m = m->next) {
- m->scale.x /= vars->scalefactor;
- m->scale.y /= vars->scalefactor;
- m->scale.z /= vars->scalefactor;
- }
- unsubscribe(&wideyeTemplate, target);
- }
- }
- }
- doSound(BUG_EYE);
- return self;
- }
-
- /*
- * DOIT for faders.
- */
- behavior *
- fadeOut(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- faderVars *vars;
-
- if (vars = (faderVars *)findvars(target, FADER)) {
- if (--vars->age == 0) {
- unsubscribe(us, target);
- unsubscribe(&faderTemplate, target);
- Msg(target, FREE, NOARG, NULL); /* get rid of all nested memory */
-
- return NULL;
- }
- }
-
- return self;
- }
-
- /*
- * trail ghosts behind target.
- */
- behavior *
- trailGhosts(self, argtype, target)
- behavior *self;
- int argtype;
- register individual *target;
- {
- trailGhostVars *vars;
- individual *ghost;
-
- if (vars = (trailGhostVars *)findvars(target, TRAIL_GHOSTS)) {
- vars->tic = vars->tic++ % vars->frequency;
- if (!vars->tic) {
- /* drop a new ghost */
- ghost = (individual *)clone(&ghostTemplate);
- Msg(ghost, INIT, NOARG, NULL);
- subscribe(us, ghost);
- ghost->position = target->position;
- }
- }
-
- return self;
- }
-